package com.elite.groovy.callback

import com.elite.groovy.kh.KHDBConfig
import com.elite.groovy.kh.KHUtil
import com.elite.groovy.kh.LogToDB
import com.elite.groovy.util.EliteBean
import com.elite.groovy.util.Util
import net.sf.json.JSONObject
import org.apache.commons.codec.digest.DigestUtils
import org.slf4j.Logger
import org.slf4j.LoggerFactory

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

/**
 * @projectName: ngsapi_cs
 * @package: cn.com.callback
 * @className: ApiSecurityCheck
 * @author: Rick
 * @description: Websocket API 安全校验回调处理类
 * @date: 2024-04-25 11:03
 * @version: 1.0
 */
public class apiSecurityCheck implements ServiceBackInvoke {
    private static final Logger log = LoggerFactory.getLogger(apiSecurityCheck.class);
    private static String tmp_Info = "";

    public String doCallBack(EliteBean eliteBean, HttpServletRequest request, HttpServletResponse response) {
        log.info("开始执行防伪码查询校验回调处理");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        long startTime = System.currentTimeMillis();
        JSONObject resJson = new JSONObject();
        String resStr = "";
        String callBody = "";
        boolean resIsXK = false; // 修正变量命名

        String davcoResultStr = "";  // 德高接口结果
        String sikaResultStr = "";   // 西卡接口结果

        try {
            String method = request.getMethod();
            log.debug("接收到HTTP请求方法类型: {}", method);

            if (!"POST".equals(method)) {
                String errorMsg = "HTTP请求调用类型错误，接口调用失败：" + method;
                log.error(errorMsg);
                resJson.put("msg", errorMsg);
                resStr = resJson.toString();
                return resStr;
            }

            // 记录请求头信息
            Map<String, String> headerMap = new HashMap<String, String>();
            Enumeration headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String key = (String) headerNames.nextElement();
                String value = request.getHeader(key);
                log.debug("请求头 - {}: {}", key, value);
                headerMap.put(key, value);
            }

            // 记录请求参数信息
            Map<String, String> paramMap = new HashMap<String, String>();
            Enumeration paramNames = request.getParameterNames();
            while (paramNames.hasMoreElements()) {
                String key = (String) paramNames.nextElement();
                String value = request.getParameter(key);
                log.debug("请求参数 - {}: {}", key, value);
                paramMap.put(key, value);
            }

            // 获取请求体
            callBody = Util.getRequestBody(request, "UTF-8");
            log.info("接收POST请求体内容: {}", callBody);
            if (isEmpty(callBody)) {
                log.error("请求体内容为空");
                resJson.put("Type", 4);
                resJson.put("msg", "请求体内容为空");
                resStr = resJson.toString();
                return resStr;
            }

            // 解析请求体JSON
            JSONObject callJson = JSONObject.fromObject(callBody);
            log.debug("请求体JSON解析完成: {}", callJson);

            // 1- 调用德高防伪查询
            log.info("开始调用德高防伪查询接口");
            JSONObject davcoResJson = callDavcoAPI_Deal(eliteBean, callJson);
            davcoResultStr = davcoResJson.toString();  // 保存德高接口原始结果
            log.debug("德高防伪查询接口处理结果: {}", davcoResJson);

            // 2- 检查是否需要调用西卡防伪
            resIsXK = isEmpty(KHUtil.GetSFJV(davcoResJson.getJSONObject("data"),"IsXK"))?false: KHUtil.GetSFJV(davcoResJson.getJSONObject("data"), "IsXK").equals("true");
            log.info("判断是否需要调用西卡接口: {}", resIsXK);

            // 3- 调用西卡防伪查询或直接使用德高结果
            if (resIsXK) {
                log.info("开始调用西卡防伪查询接口");
                JSONObject sikaResJson = sikaSecuritySearchCode(eliteBean, callJson);
                sikaResultStr = sikaResJson.toString();  // 保存西卡接口原始结果
                log.debug("西卡防伪查询接口返回结果: {}", sikaResJson);

                if ("1".equals(KHUtil.GetSFJV(sikaResJson, "code"))) {
                    log.info("西卡接口返回正品结果，使用西卡数据");
                    resJson = sikaResJson.getJSONObject("data");
                } else {
                    log.info("西卡接口返回非正品结果，使用德高数据");
                    resJson = davcoResJson.getJSONObject("data");
                }
            } else {
                log.info("无需调用西卡接口，直接使用德高数据");
                resJson = davcoResJson.getJSONObject("data");
            }

            resStr = resJson.toString();
            log.debug("最终返回结果组装完成: {}", resStr);

        } catch (Exception e) {
            log.error("全局处理异常", e); // 打印完整堆栈
            resJson.put("Type", 4);
            resJson.put("msg", "全局处理异常: " + e.getMessage());
            resStr = resJson.toString();
        } finally {
            long costTime = System.currentTimeMillis() - startTime;
            log.info("本次防伪码查询校验处理总耗时: {}ms", costTime);

            // 修改LogToDB调用：新增德高和西卡结果记录
            String logRemark = String.format(
                    "德高接口结果:%s\n\n" +
                            "IsXK:%s\n\n" +
                            "西卡接口结果:%s\n\n" +
                            "接口结果:%s",
                    davcoResultStr,
                    resIsXK,
                    sikaResultStr,
                    resStr
            );

            LogToDB.toDB(eliteBean, "dataSource", "apiSecurityCheck[*]", "apiSecurityCheck",
                    callBody, logRemark, "本次发送总耗时：" + costTime, "IsXK:" + resIsXK);
        }

        return resStr;
    }

    /**
     * 处理德高API调用及结果转换
     */
    public static JSONObject callDavcoAPI_Deal(EliteBean eliteBean, JSONObject callJson) {
        log.info("开始处理德高API调用结果");
        JSONObject resJson = new JSONObject();
        JSONObject dataJson = new JSONObject();

        try {
            String callResultStr = davcoSecuritySearchCode(eliteBean, callJson);
            log.debug("德高防伪查询接口原始返回: {}", callResultStr);

            resJson = JSONObject.fromObject(callResultStr);
            String resCode = resJson.get("code");
            log.debug("德高接口返回状态码: {}", resCode);

            // 处理德高接口返回结果
            if ("1".equals(resCode)) { // 修正字符串比较方式
                dataJson = resJson.getJSONObject("data");
                log.debug("德高接口返回数据: {}", dataJson);

                // 分析映射接口和IVR播报语言的类型
                int resType = doIVRToFlowType(dataJson);
                log.debug("IVR流程类型转换结果: {}", resType);

                dataJson.put("Type", resType);
                resJson.put("data", dataJson);
            } else {
                // 接口返回不正常时的默认处理
                log.warn("德高接口返回非成功状态码: {}", resCode);
                dataJson.put("Type", 4);
                dataJson.put("IsXK", true); // 接口异常时查询西卡接口
                resJson.put("data", dataJson);
            }
        } catch (Exception e) {
            log.error("德高API结果处理异常", e);
            dataJson.put("Type", 4);
            dataJson.put("IsXK", true);
            resJson.put("data", dataJson);
        }

        return resJson;
    }

    /**
     * 德高防伪查询方法
     */
    public static String davcoSecuritySearchCode(EliteBean eliteBean, JSONObject bodyJson) {
        log.info("开始调用德高防伪查询接口");
        JSONObject resJson = new JSONObject();
        try {
            // 获取请求参数
            String codeId = bodyJson.get("CodeId");
            boolean isStat = bodyJson.get("IsStat");
            String queryArgs = bodyJson.get("QueryArgs");
            String queryKind = bodyJson.get("QueryKind");
            String queryType = bodyJson.get("QueryType");
            String queryUser = bodyJson.get("QueryUser");

            log.debug("德高接口请求参数 - CodeId: {}, IsStat: {}, QueryArgs: {}, QueryKind: {}, QueryType: {}, QueryUser: {}",
                    codeId, isStat, queryArgs, queryKind, queryType, queryUser);

            // 获取接口地址
            String url = KHDBConfig.getAPIURL(eliteBean, "SecuritySearchCode");
            log.debug("德高接口请求地址: {}", url);

            // 构建请求头
            Map<String, String> headMap = new HashMap<String, String>();
            headMap.put("Content-Type", "application/json");

            // 构建请求体
            JSONObject requestBody = new JSONObject();
            requestBody.put("CodeId", codeId);
            requestBody.put("IsStat", isStat);
            requestBody.put("QueryArgs", queryArgs);
            requestBody.put("QueryKind", queryKind);
            requestBody.put("QueryType", queryType);
            requestBody.put("QueryUser", queryUser);
            String requestBodyStr = requestBody.toString();
            log.debug("德高接口请求体: {}", requestBodyStr);

            // 调用接口
            String responseResult = Util.doHttpPostUseHead(url, requestBodyStr, "UTF-8", 120000, 0, headMap);
            log.debug("德高接口原始响应: {}", responseResult);

            // 处理响应结果
            JSONObject responseJson = JSONObject.fromObject(responseResult);
            responseJson.put("TQR", ""); // 覆盖超长字段
            resJson.put("code", "1");
            resJson.put("data", responseJson); // 直接存JSONObject而非String
            resJson.put("msg", "接口正常");

        } catch (Exception e) {
            log.error("德高防伪查询接口调用异常", e);
            resJson.put("code", "-1");
            resJson.put("data", "");
            resJson.put("msg", "德高接口处理异常: " + e.getMessage());
        }

        return resJson.toString();
    }

    /**
     * 西卡防伪查询方法
     */
    public static JSONObject sikaSecuritySearchCode(EliteBean eliteBean, JSONObject bodyJson) {
        log.info("开始调用西卡防伪查询接口");
        JSONObject resJson = new JSONObject();
        try {
            String codeId = bodyJson.get("CodeId");
            log.debug("西卡接口请求参数 - CodeId: {}", codeId);

            // 获取接口地址和配置信息
            String url = KHDBConfig.getAPIURL(eliteBean, "GetdgSecurityCodeKind");
            String signInfo = KHDBConfig.getSignInfo(eliteBean, "XK_GetdgSecurityCodeKind");
            JSONObject signInfoJson = JSONObject.fromObject(signInfo);

            String xkUserid = signInfoJson.get("userid");
            String xkPassword = signInfoJson.get("Password");
            String xkSikaWinsafe = signInfoJson.get("SikaWinsafe");
            log.debug("西卡接口配置 - URL: {}, UserId: {}, SikaWinsafe: {}", url, xkUserid, xkSikaWinsafe.replaceAll(".", "*")); // 脱敏显示密钥

            // 构建请求参数（添加URL编码）
            StringBuffer formData = new StringBuffer();
            formData.append("userid=").append(URLEncoder.encode(xkUserid, "UTF-8"));
            formData.append("&password=").append(URLEncoder.encode(xkPassword, "UTF-8"));
            formData.append("&callerid=").append(URLEncoder.encode("00000000000", "UTF-8"));
            formData.append("&code=").append(URLEncoder.encode(codeId, "UTF-8"));

            String noSignPostUrl = url + formData.toString();
            log.debug("西卡接口无签名请求URL: {}", noSignPostUrl);

            // 生成签名
            String sign = shortText(noSignPostUrl, xkSikaWinsafe);
            log.debug("西卡接口生成签名: {}", sign);

            // 构建完整请求URL
            String yesSignPostUrl = url + formData.toString() + "&sign=" + URLEncoder.encode(sign, "UTF-8");
            log.debug("西卡接口完整请求URL: {}", yesSignPostUrl);

            // 调用接口
            String xkResponseResult = Util.doHttpPost(yesSignPostUrl, "", "UTF-8", 120000, 0);
            log.debug("西卡接口原始响应: {}", xkResponseResult);

            // 处理响应结果
            JSONObject xkResponseJson = JSONObject.fromObject(xkResponseResult);
            String chrTrue = KHUtil.GetSFJV(xkResponseJson, "chrTrue");
            log.debug("西卡接口真伪标识: {}", chrTrue);

            if ("1".equals(chrTrue)) {
                xkResponseJson.put("Succeess", true);
                xkResponseJson.put("Type", 13);
                resJson.put("code", "1");
                resJson.put("data", xkResponseJson);
                resJson.put("msg", "真");
            } else {
                xkResponseJson.put("Succeess", true);
                xkResponseJson.put("Type", 13);
                resJson.put("code", "0");
                resJson.put("data", xkResponseJson);
                resJson.put("msg", "假");
            }
        } catch (Exception e) {
            log.error("西卡防伪查询接口调用异常", e);
            resJson.put("code", "-1");
            resJson.put("data", "");
            resJson.put("msg", "西卡接口处理异常: " + e.getMessage());
        }

        return resJson;
    }

    /**
     * 西卡接口签名方法
     */
    public static String shortText(String url, String sikaWinsafe) {
        log.debug("开始生成西卡接口签名");
        String key = sikaWinsafe;
        String[] chars = new String[]{
                "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
                "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
                "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B",
                "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
                "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
        };

        String hex = DigestUtils.md5Hex(key + url);
        int hexLen = hex.length();
        int subHexLen = hexLen / 8;
        String[] shortStr = new String[subHexLen]; // 修正拼写错误

        for (int i = 0; i < subHexLen; i++) {
            String outChars = "";
            int j = i + 1;
            String subHex = hex.substring(i * 8, j * 8);
            long idx = Long.valueOf("3FFFFFFF", 16) & Long.valueOf(subHex, 16);

            for (int k = 0; k < 6; k++) {
                int index = (int) (Long.valueOf("0000003D", 16) & idx);
                outChars += chars[index];
                idx = idx >> 5;
            }
            shortStr[i] = outChars;
        }

        log.debug("西卡接口签名生成完成");
        return shortStr[0].toString();
    }

    /**
     * 转换IVR类型到流程类型
     */
    public static int doIVRToFlowType(JSONObject dataJson) {
        log.info("开始转换IVR类型到流程类型，输入数据: {}", dataJson);
        if (dataJson == null) {
            log.warn("输入数据为null，返回系统异常类型4");
            return 4;
        }

        String type = KHUtil.GetSFJV(dataJson, "Type");
        String successStr = KHUtil.GetSFJV(dataJson, "Succeess");
        boolean isSuccess = "true".equalsIgnoreCase(successStr);

        log.debug("IVR类型转换参数 - Type: {}, Succeess: {}, 转换后布尔值: {}", type, successStr, isSuccess);

        switch (type) {
            case "10":
                log.debug("处理Type=10的情况，Succeess={}", isSuccess);
                return isSuccess ? 4 : 1;
            case "4":
                log.debug("处理Type=4的情况，Succeess={}", isSuccess);
                return isSuccess ? 4 : 1;
            case "3":
                log.debug("处理Type=3的情况，Succeess={}", isSuccess);
                if (!isSuccess) {
                    log.debug("Type=3且Succeess=false，返回假货提示类型0");
                    return 0;
                } else {
                    // 检查产品信息字段是否为空
                    String productName = KHUtil.GetSFJV(dataJson, "ProductName");
                    String produceDate = KHUtil.GetSFJV(dataJson, "ProduceDate");
                    String color = KHUtil.GetSFJV(dataJson, "Color");

                    boolean isProductNameEmpty = isEmpty(productName);
                    boolean isProduceDateEmpty = isEmpty(produceDate);
                    boolean isColorEmpty = isEmpty(color);

                    log.debug("产品信息字段检查 - ProductName为空: {}, ProduceDate为空: {}, Color为空: {}",
                            isProductNameEmpty, isProduceDateEmpty, isColorEmpty);

                    if (isProductNameEmpty && isProduceDateEmpty && isColorEmpty) {
                        String corpName = KHUtil.GetSFJV(dataJson, "ProduceCorpName");
                        log.debug("所有产品字段为空，公司名称: {}", corpName);
                        return corpName.contains("西卡") ? 13 : 9;
                    } else {
                        log.debug("存在非空产品字段，返回德高正品类型3");
                        return 3;
                    }
                }
            case "0":
                log.debug("处理Type=0的情况，Succeess={}", isSuccess);
                return isSuccess ? 4 : 2;
            default:
                log.warn("未知的Type值: {}, 返回系统异常类型4", type);
                return 4;
        }
    }

    /**
     * 辅助方法：判断字符串是否为空
     */
    private static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
}